package com.zed.games.repository;

import com.zed.api.domain.currentuser.Account;
import com.zed.api.domain.currentuser.CurrentUserUtils;
import com.zed.api.games.Game;
import com.zed.api.games.GameQueryRepository;
import com.zed.api.games.ImmutableGameWrapper;
import com.zed.games.GameRegister;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * 运行时游戏仓储
 *
 * @author Zed
 */
public class RunningGameRepository implements GameQueryRepository, GameRegister {

    /**
     * key: account id , value: Game
     */
    private Map<String, List<ImmutableGameWrapper>> accountGameMap;
    /**
     * key: gameId, value: Game
     */
    private Map<String, ImmutableGameWrapper> gameMap;

    public RunningGameRepository() {
        this.accountGameMap = new ConcurrentHashMap<>();
        this.gameMap = new ConcurrentHashMap<>();
    }

    /**
     * 获取不可变的在线游戏集合
     *
     * @return {@link List},集合
     */
    @Override
    public List<Game> getGames() {
        return List.copyOf(this.accountGameMap.values()
                .stream()
                .flatMap(Collection::stream)
                .collect(Collectors.toList()));
    }

    @Override
    public Game getAccountRunningGame(String gameBuilderId) {
        String accountId = CurrentUserUtils.getAccountWithCurrentUser().getId();
        List<ImmutableGameWrapper> games = this.accountGameMap.get(accountId);

        for (Game game : games) {
            if (game.isGameBuilder(gameBuilderId)) {
                return game;
            }
        }

        return null;
    }

    @Override
    public List<Game> getAccountRunningGames() {
        return this.accountGameMap.get(CurrentUserUtils.getAccountWithCurrentUser().getId())
                .stream()
                .map(ImmutableGameWrapper.class::cast)
                .collect(Collectors.toList());
    }

    @Override
    public Game findById(String id) {
        return this.gameMap.get(id);
    }

    @Override
    public List<Game> getByIds(Collection<String> ids) {
        if (ids == null || ids.isEmpty()) return Collections.emptyList();
        List<Game> result = new ArrayList<>();
        for (String id : ids) {
            result.add(this.gameMap.get(id));
        }
        return result;
    }

    @Override
    public void register(ImmutableGameWrapper game) {
        Account account = CurrentUserUtils.getAccountWithCurrentUser();
        List<ImmutableGameWrapper> games = this.accountGameMap.computeIfAbsent(account.getId(), id -> new CopyOnWriteArrayList<>());
        games.add(game);
        this.gameMap.put(game.getId(), game);
    }

    @Override
    public void unRegistet(ImmutableGameWrapper game) {
        Account account = CurrentUserUtils.getAccountWithCurrentUser();

        this.accountGameMap.computeIfPresent(account.getId(), (accountId, games) -> {
            games.remove(game);
            return games;
        });

        this.gameMap.remove(game.getId());
    }
}
